package com.slw.emergency.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.slw.emergency.entity.*;
import com.slw.emergency.enums.StatusEnum;
import com.slw.emergency.model.*;
import com.slw.emergency.service.*;
import com.slw.emergency.util.*;
import eu.bitwalker.useragentutils.Browser;
import eu.bitwalker.useragentutils.OperatingSystem;
import eu.bitwalker.useragentutils.UserAgent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class QueryServiceImpl implements QueryService {
    private Logger logger = LoggerFactory.getLogger(QueryServiceImpl.class);

    @Autowired
    private EmergencyDetailService emergencyDetailService;

    @Autowired
    private LogVisitService logVisitService;

    @Autowired
    private EpidemicService epidemicService;

    @Autowired
    private EmergencyVillageServiceImpl emergencyVillageService;

    @Autowired
    private OverseaEpidemicService overseaEpidemicService;

    @Override
    public List<RespCityModel> getDetailByCity(String province,String city) {
        List<EmergencyDetail> emergencyDetailList = emergencyDetailService
                .list(new QueryWrapper<EmergencyDetail>().lambda()
                        .like(!StringUtils.isEmpty(province),EmergencyDetail::getProvince,province)
                        .like(!StringUtils.isEmpty(city),EmergencyDetail::getCity,city)
                .eq(EmergencyDetail::getWhetherNow,StatusEnum.YES.getStutus()));
        List<RespCityModel> respCityModels = new ArrayList<>();
        for (EmergencyDetail emergencyDetail : emergencyDetailList){
            RespCityModel respCityModel = new RespCityModel();
            BeanUtils.copyProperties(emergencyDetail,respCityModel);
            respCityModels.add(respCityModel);
        }
        return respCityModels;
    }
    public List<RespCityModel> getDetailByCellName(String cellName,String city) {
        List<EmergencyDetail> emergencyDetailList = emergencyDetailService
                .list(new QueryWrapper<EmergencyDetail>().lambda()
                        .eq(EmergencyDetail::getWhetherNow,StatusEnum.YES.getStutus())
                        .like(!StringUtils.isEmpty(city),EmergencyDetail::getCity,city)
                        .and(s -> s.like(!StringUtils.isEmpty(cellName),EmergencyDetail::getCommunity,cellName).or()
                                  .like(!StringUtils.isEmpty(cellName),EmergencyDetail::getStreet,cellName)));
//                        .like(!StringUtils.isEmpty(cellName),EmergencyDetail::getCommunity,cellName)
//                        .like(!StringUtils.isEmpty(cellName),EmergencyDetail::getStreet,cellName));
        List<RespCityModel> respCityModels = new ArrayList<>();
        for (EmergencyDetail emergencyDetail : emergencyDetailList){
            RespCityModel respCityModel = new RespCityModel();
            BeanUtils.copyProperties(emergencyDetail,respCityModel);
            respCityModels.add(respCityModel);
        }
        return respCityModels;
    }
    @Override
    public List<RespCityDistanceModel> getDistanceByCity(String province, String city, double lon, double lat) {
        List<RespCityModel> respCityModels = getDetailByCity(province,city);
        List<RespCityDistanceModel> respCityDistanceModels = new ArrayList<>();
        for (RespCityModel respCityModel : respCityModels){
            RespCityDistanceModel respCityDistanceModel = new RespCityDistanceModel();
            BeanUtils.copyProperties(respCityModel,respCityDistanceModel);
            respCityDistanceModel.setDistance(Math.abs(GPSUtil.GetDistance(lon,lat,respCityModel.getLng(),respCityModel.getLat())));
            respCityDistanceModels.add(respCityDistanceModel);
        }
        return respCityDistanceModels.stream().filter(respCityDistanceModel -> respCityDistanceModel.getDistance()<=15*1000)
                .sorted(Comparator.comparing(RespCityDistanceModel::getDistance))
                .collect(Collectors.toList());
    }

    @Override
    public void insertDetail(boolean isUpdate) {
        //https://ncov.html5.qq.com/api/getCommunity?province=%E6%B2%B3%E5%8D%97%E7%9C%81&city=%E9%83%91%E5%B7%9E%E5%B8%82&district=%E5%B7%A9%E4%B9%89%E5%B8%82
        //String str = "{\"code\":0,\"community\":{\"河南省\":{\"郑州市\":{\"上街区\":[{\"province\":\"河南省\",\"city\":\"郑州市\",\"district\":\"上街区\",\"county\":\"\",\"street\":\"\",\"community\":\"沙固新村\",\"show_address\":\"沙固新村\",\"cnt_inc_uncertain\":\"-1\",\"cnt_inc_certain\":\"-1\",\"cnt_inc_die\":\"-1\",\"cnt_inc_recure\":\"-1\",\"cnt_sum_uncertain\":\"-1\",\"cnt_sum_certain\":\"1\",\"cnt_sum_die\":\"-1\",\"cnt_sum_recure\":\"-1\",\"full_address\":\"河南省郑州市上街区沙固新村\",\"lng\":\"113.258034\",\"lat\":\"34.81657\",\"source\":[{\"name\":\"郑州发布\",\"url\":\"\"}],\"distance\":-1}]}}}}";
        String url = "https://ncov.html5.qq.com/api/getCommunity";
        List<EmergencyDetail> insertList = new ArrayList<>();
        Map<String,String> param = new HashMap<>();
        param.put("province","");
        String responseBody = OkHttpUtil.get(url,param);
        List<EmergencyDetail> emergencyDetailList = AnalysisUtil.getList(responseBody);
        if (isUpdate){
            EmergencyDetail emergencyDetail = new EmergencyDetail();
            emergencyDetail.setWhetherNow(StatusEnum.NO.getStutus());
            emergencyDetailService.update(emergencyDetail,new UpdateWrapper<>());
        }
        emergencyDetailService.saveBatch(emergencyDetailList);
    }
//    public void saveOrUpdateDetail() {
//        String url = "https://ncov.html5.qq.com/api/getCommunity";
//        List<EmergencyDetail> insertList = new ArrayList<>();
//        Map<String,String> param = new HashMap<>();
//        param.put("province","");
//        String responseBody = OkHttpUtil.get(url,param);
//        List<EmergencyDetail> emergencyDetailList = AnalysisUtil.getList(responseBody);
//        for (EmergencyDetail detail :emergencyDetailList) {
//            EmergencyDetail emergencyDetail =null;
//            emergencyDetail = emergencyDetailService.getOne(new QueryWrapper<EmergencyDetail>().lambda().
//                    eq(EmergencyDetail::getCellId, detail.getCellId()));
//            Date now=new Date();
//            if (emergencyDetail !=null) {
//                detail.setId(emergencyDetail.getId());
//                detail.setModifyTime(now);
//                if (!detail.equals(emergencyDetail)) {
//                    emergencyDetailService.updateById(detail);
//                }
//            } else {
//                detail.setModifyTime(now);
//                emergencyDetailService.save(detail);
//            }
//
//        }
//    }

    @Override
    public void insertEpidemic() {
        String url = "https://c.m.163.com/ug/api/wuhan/app/data/list-total";
//        String responseBody = OkHttpUtil.get(url,new HashMap<>());
        String responseBody = OkHttpUtil.doGet(url);
        //获取中国疫情数据
        List<Epidemic> epidemics = JsonUtil.jsonResolveChina(responseBody);
        //更新中国数据
        //将所有的全部标记为非最新
        Epidemic updateEpi = new Epidemic();
        updateEpi.setIsLatest(StatusEnum.NO.getStutus());
        epidemicService.update(updateEpi,new UpdateWrapper<Epidemic>().lambda().eq(Epidemic::getCreateTime,new Date()));
        //批量更新
        epidemicService.saveBatch(epidemics);

        //获取海外疫情数据
        List<OverseaEpidemic> overseaEpidemics = JsonUtil.jsonResolveOver(responseBody);
        //更新海外数据
        OverseaEpidemic updateOversea = new OverseaEpidemic();
        updateOversea.setIsLatest(StatusEnum.NO.getStutus());
        overseaEpidemicService.update(updateOversea,new UpdateWrapper<OverseaEpidemic>().lambda().eq(OverseaEpidemic::getCreateTime,new Date()));
        //批量更新
        overseaEpidemicService.saveBatch(overseaEpidemics);

    }

    @Override
    public void countVisit(HttpServletRequest request) {
        LogVisit logVisit = new LogVisit();
        UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));

        //获取浏览器信息
        Browser browser = userAgent.getBrowser();

        //获取操作系统信息
        OperatingSystem os = userAgent.getOperatingSystem();

        logVisit.setVisitTime(new Date());
        logVisit.setBrowser(browser.toString());
        logVisit.setOs(os.toString());
        logVisit.setIpAddr(WebUtil.getIPAddress(request));
        logVisitService.save(logVisit);
    }

    @Override
    public Map<String, Object> getSpaceChange() {
        Map<String,Object> retMap = new HashMap<>();

        //city使用map
        Map<String,List<Epidemic>> tempMap = getMapByTime();

        retMap.put("cityMap",resolveCityMap(tempMap));
        retMap.put("provinceMap",getProvinceMap(tempMap));
        return retMap;
    }

    private Map<String,List<RespEpiCityModel>> resolveCityMap(Map<String,List<Epidemic>> tempMap){
        Map<String,List<RespEpiCityModel>> retMap = new HashMap<>();
        tempMap.forEach((k,v)->{
            List<RespEpiCityModel> respCityModels = new ArrayList<>();
            v.forEach(epidemic -> {
                RespEpiCityModel respCityModel = new RespEpiCityModel();
                BeanUtils.copyProperties(epidemic,respCityModel);
                respCityModels.add(respCityModel);
            });
            retMap.put(k,respCityModels);
        });

        Map<String,List<RespEpiCityModel>> result = new LinkedHashMap<>();
        retMap.entrySet().stream().sorted((stringListEntry, t1) -> {
            String str1 = stringListEntry.getKey();
            String str2 = t1.getKey();
            int i = 0;
            try{
                SimpleDateFormat df = new SimpleDateFormat("yyyy.MM.dd");
                Date d1 = df.parse(str1);
                Date d2 = df.parse(str2);
                i = d1.compareTo(d2);
            }catch (Exception e){
                e.printStackTrace();
            }
            return i;
        }).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
            return result;
    }

    /**
     * 获取省份计算总量
     * @return
     */
    private Map<String,List<RespEpiProvinceModel> > getProvinceMap(Map<String,List<Epidemic>> tempMap ){
        Map<String,List<RespEpiProvinceModel>> retMap = new HashMap<>();
        tempMap.forEach((k,v)->{
            retMap.put(k,countProvince(v));
        });
        Map<String,List<RespEpiProvinceModel>> result = new LinkedHashMap<>();
        retMap.entrySet().stream().sorted((stringListEntry, t1) -> {
            String str1 = stringListEntry.getKey();
            String str2 = t1.getKey();
            int i = 0;
            try{
                SimpleDateFormat df = new SimpleDateFormat("yyyy.MM.dd");
                Date d1 = df.parse(str1);
                Date d2 = df.parse(str2);
                i = d1.compareTo(d2);
            }catch (Exception e){
                e.printStackTrace();
            }
            return i;
        }).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        return result;
    }


    /**
     * 根据省份计算总量
     * @return
     */
    private List<RespEpiProvinceModel> countProvince(List<Epidemic> epidemics){
        List<RespEpiProvinceModel> respEpidemicModels = new ArrayList<>();
        Map<String,List<Epidemic>> epidemicMap = new HashMap<>();
        epidemics.forEach(epidemic -> {
            String province = epidemic.getProvince();
            List<Epidemic> epidemicList = epidemicMap.get(province);
            if (CollectionUtils.isEmpty(epidemicList)){
                epidemicList = new ArrayList<>();
            }
            epidemicList.add(epidemic);
            epidemicMap.put(province,epidemicList);
        });

        epidemicMap.forEach((k,v)->{
            RespEpiProvinceModel respEpidemicModel = new RespEpiProvinceModel();
            int suspected = 0;
            int confirmed = 0;
            int dead = 0;
            int cured = 0;
            for (Epidemic epidemic : v){
                suspected = suspected + Integer.valueOf(epidemic.getCntSumSuspected());
                confirmed = confirmed + Integer.valueOf(epidemic.getCntSumConfirmed());
                dead = dead + Integer.valueOf(epidemic.getCntSumDead());
                cured = cured + Integer.valueOf(epidemic.getCntSumCured());
            }
            respEpidemicModel.setProvince(k);
            respEpidemicModel.setCntSumSuspected(String.valueOf(suspected));
            respEpidemicModel.setCntSumConfirmed(String.valueOf(confirmed));
            respEpidemicModel.setCntSumDead(String.valueOf(dead));
            respEpidemicModel.setCntSumCured(String.valueOf(cured));
            respEpidemicModel.setLat(JsonUtil.getLng(k)[1]);
            respEpidemicModel.setLng(JsonUtil.getLng(k)[0]);
            respEpidemicModels.add(respEpidemicModel);
        });
        return  respEpidemicModels;
    }
    /**
     * 根据时间戳拆分list
     * @return
     */
    private Map<String,List<Epidemic>> getMapByTime(){
        Map<String,List<Epidemic>> tempMap = new HashMap<>();
        List<Epidemic> epidemics = epidemicService.list(new QueryWrapper<Epidemic>().lambda()
                .eq(Epidemic::getIsLatest,StatusEnum.YES.getStutus()));
        epidemics.forEach(epidemic -> {
            try{
                SimpleDateFormat df = new SimpleDateFormat("yyyy.MM.dd");
                String strDate = df.format(epidemic.getCreateTime());
                List<Epidemic> epidemicList = tempMap.get(strDate);
                if (CollectionUtils.isEmpty(epidemicList)){
                    epidemicList = new ArrayList<>();
                }
                epidemicList.add(epidemic);
                tempMap.put(strDate,epidemicList);
            }catch (Exception e){
                logger.error(e.getMessage(),e);
            }
        });
        return tempMap;
    }

    @Override
    public Map<String, Object> getVillage() {
        Map<String,Object> retMap = new HashMap<>();

        Map<String,List<EmergencyVillage>> tempMap = getTimeVillage();
        List<RespVillCommutyModel> commutyMap = emergencyVillageService.getCommutyMap();
        List<RespVillDistctModel> distctMap = emergencyVillageService.getDistctMap();

        retMap.put("commutyMap",getCommutyMapV(tempMap,commutyMap));
        retMap.put("districtMap",getDistctMapV(tempMap,distctMap));
        return retMap;
    }

    private Map<String,List<EmergencyVillage>> getTimeVillage(){
        Map<String,List<EmergencyVillage>> tempMap = new HashMap<>();
        List<EmergencyVillage> epidemics = emergencyVillageService.list(new QueryWrapper<EmergencyVillage>());
        epidemics.forEach(epidemic -> {
            try{
                SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
                String strDate = df.format(epidemic.getDiagnosisTime());
                List<EmergencyVillage> epidemicList = tempMap.get(strDate);
                if (CollectionUtils.isEmpty(epidemicList)){
                    epidemicList = new ArrayList<>();
                }
                epidemicList.add(epidemic);
                tempMap.put(strDate,epidemicList);
            }catch (Exception e){
                logger.error(e.getMessage(),e);
            }
        });
        return tempMap;
    }

    private Map<String,List<RespVillDistctModel>> getDistctMapV(Map<String,List<EmergencyVillage>> tempMap,List<RespVillDistctModel> commutyMap){
        Map<String,List<RespVillDistctModel>> retMap = new HashMap<>();
        tempMap.forEach((k,v)->{
            List<RespVillDistctModel> respCityModels = new ArrayList<>();
            commutyMap.forEach(epidemic -> {
                if(epidemic.getVtime().trim().equals(k)){
                    respCityModels.add(epidemic);
                }
            });
            retMap.put(k,respCityModels);
        });

        Map<String,List<RespVillDistctModel>> result = new LinkedHashMap<>();
        retMap.entrySet().stream().sorted((stringListEntry, t1) -> {
            String str1 = stringListEntry.getKey();
            String str2 = t1.getKey();
            int i = 0;
            try{
                SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
                Date d1 = df.parse(str1);
                Date d2 = df.parse(str2);
                i = d1.compareTo(d2);
            }catch (Exception e){
                e.printStackTrace();
            }
            return i;
        }).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        return result;
    }

    private Map<String,List<RespVillCommutyModel>> getCommutyMapV(Map<String,List<EmergencyVillage>> tempMap,List<RespVillCommutyModel> commutyMap){
        Map<String,List<RespVillCommutyModel>> retMap = new HashMap<>();
        tempMap.forEach((k,v)->{
            List<RespVillCommutyModel> respCityModels = new ArrayList<>();
            commutyMap.forEach(epidemic -> {
                if(epidemic.getVtime().trim().equals(k)){
                    respCityModels.add(epidemic);
                }
            });
            retMap.put(k,respCityModels);
        });

        Map<String,List<RespVillCommutyModel>> result = new LinkedHashMap<>();
        retMap.entrySet().stream().sorted((stringListEntry, t1) -> {
            String str1 = stringListEntry.getKey();
            String str2 = t1.getKey();
            int i = 0;
            try{
                SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
                Date d1 = df.parse(str1);
                Date d2 = df.parse(str2);
                i = d1.compareTo(d2);
            }catch (Exception e){
                e.printStackTrace();
            }
            return i;
        }).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        return result;
    }

    //commuty
    private Map<String,List<RespVillCommutyModel>> getCommutyMap(Map<String,List<EmergencyVillage>> tempMap){
        Map<String,List<RespVillCommutyModel>> retMap = new HashMap<>();
        tempMap.forEach((k,v)->{
            List<RespVillCommutyModel> respCityModels = new ArrayList<>();
            v.forEach(epidemic -> {
                //小区重复问题
                RespVillCommutyModel respCityModel = new RespVillCommutyModel();
                BeanUtils.copyProperties(epidemic,respCityModel);
                //cntConfirm
                int cnt = 0;
                SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
                try {
                    cnt = emergencyVillageService.count(new QueryWrapper<EmergencyVillage>().lambda()
                               .eq(EmergencyVillage::getCommunity,epidemic.getCommunity())
                               .eq(EmergencyVillage::getDiagnosisTime,df.parse(k.replaceAll("\\.","-"))));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                respCityModel.setCntSumConfirmed(String.valueOf(cnt));
                respCityModels.add(respCityModel);
            });
            retMap.put(k,respCityModels);
        });

        Map<String,List<RespVillCommutyModel>> result = new LinkedHashMap<>();
        retMap.entrySet().stream().sorted((stringListEntry, t1) -> {
            String str1 = stringListEntry.getKey();
            String str2 = t1.getKey();
            int i = 0;
            try{
                SimpleDateFormat df = new SimpleDateFormat("yyyy.MM.dd");
                Date d1 = df.parse(str1);
                Date d2 = df.parse(str2);
                i = d1.compareTo(d2);
            }catch (Exception e){
                e.printStackTrace();
            }
            return i;
        }).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        return result;
    }

    //distct
    private Map<String,List<RespVillDistctModel> > getDistctMap(Map<String,List<EmergencyVillage>> tempMap ){
        Map<String,List<RespVillDistctModel>> retMap = new HashMap<>();
        tempMap.forEach((k,v)->{
            retMap.put(k,countDistct(v));
        });
        Map<String,List<RespVillDistctModel>> result = new LinkedHashMap<>();
        retMap.entrySet().stream().sorted((stringListEntry, t1) -> {
            String str1 = stringListEntry.getKey();
            String str2 = t1.getKey();
            int i = 0;
            try{
                SimpleDateFormat df = new SimpleDateFormat("yyyy.MM.dd");
                Date d1 = df.parse(str1);
                Date d2 = df.parse(str2);
                i = d1.compareTo(d2);
            }catch (Exception e){
                e.printStackTrace();
            }
            return i;
        }).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        return result;
    }

    private List<RespVillDistctModel> countDistct(List<EmergencyVillage> epidemics){
        List<RespVillDistctModel> respEpidemicModels = new ArrayList<>();
        Map<String,List<EmergencyVillage>> epidemicMap = new HashMap<>();
        epidemics.forEach(epidemic -> {
            String province = epidemic.getProvince();
            List<EmergencyVillage> epidemicList = epidemicMap.get(province);
            if (CollectionUtils.isEmpty(epidemicList)){
                epidemicList = new ArrayList<>();
            }
            epidemicList.add(epidemic);
            epidemicMap.put(province,epidemicList);
        });

        epidemicMap.forEach((k,v)->{
            RespVillDistctModel respEpidemicModel = new RespVillDistctModel();
            int confirmed = 0;
            for (EmergencyVillage epidemic : v){
//                confirmed = confirmed + Integer.valueOf(epidemic.getCntSumConfirmed());
            }
            respEpidemicModel.setProvince(k);
            respEpidemicModel.setCntSumConfirmed(String.valueOf(confirmed));
//            respEpidemicModel.setLat(JsonUtil.getLng(k)[1]);
//            respEpidemicModel.setLng(JsonUtil.getLng(k)[0]);
            respEpidemicModels.add(respEpidemicModel);
        });
        return  respEpidemicModels;
    }
}
